﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Data.Common;
using System.Reflection;
using System.Text;

namespace EntityFrameworkCore.Comment
{
    public static class DbContextExtensions
    {
        private static string GetDataType(DbConnection connection, string tableName, string columnName)
        {
            var command = connection.CreateCommand();
            command.CommandText = string.Format("SELECT `COLUMN_TYPE` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA`='{0}' AND `TABLE_NAME`='{1}' AND `COLUMN_NAME`='{2}';", connection.Database, tableName, columnName);
            connection.Open();
            var scalar = command.ExecuteScalar();
            connection.Close();
            return scalar.ToString();
        }

        /// <summary>
        /// Database had better to migrate before to make sure that migration uses project's version.
        /// </summary>
        public static void AddDatabaseComments(this DbContext dbContext, bool preMigrate = false)
        {
            if (preMigrate)
                dbContext.Database.Migrate();

            if (!dbContext.Database.ProviderName.ToLower().Contains("mysql"))
                throw new NotImplementedException("Only MySql impled,impl others by yourself!\r\nhttps://gitee.com/atalent/EntityFrameworkCore.Comment.git\r\n");

            var connection = dbContext.Database.GetDbConnection();
            var sql = new StringBuilder();
            var type = dbContext.GetType();
            foreach (var table in type.GetMembers())
            {
                var tableComment = table.GetCustomAttribute<CommentAttribute>();
                if (tableComment == null)
                    continue;

                sql.AppendFormat("ALTER TABLE `{0}` COMMENT='{1}';\r\n", table.Name, tableComment.Value);

                var tableType = ((PropertyInfo)table).PropertyType;
                foreach (var column in tableType.GenericTypeArguments[0].GetMembers())
                {
                    var columnComment = column.GetCustomAttribute<CommentAttribute>();
                    if (columnComment == null)
                        continue;

                    var dataType = GetDataType(connection, table.Name, column.Name);
                    sql.AppendFormat("ALTER TABLE `{0}` MODIFY COLUMN `{1}` {2} COMMENT '{3}';\r\n", table.Name, column.Name, dataType, columnComment.Value);
                }
            }

            if (sql.Length == 0)
            {
                Console.WriteLine("\r\nAddDatabaseComments: Database Comments not found, please add CommentAttributes in DbContext and Entity.\r\n");
                return;
            }

            var result = sql.ToString();
            Console.WriteLine("\r\n" + result + "\r\n");
            dbContext.Database.ExecuteSqlCommand(result);
        }

        //private static void AddComments(this DatabaseFacade database)
        //{
        //    var migrationBuilder = new MigrationBuilder(database.ProviderName);
        //    //core 3.0
        //    migrationBuilder.AlterColumn<int>(table: "@table", name: "@name", comment: "@comment");
        //    throw new NotImplementedException();
        //}
    }
}
